package com.huaxin.common.message.mp3recorder;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;

import com.huaxin.common.tools.Log;

import java.util.LinkedList;

import static com.huaxin.common.message.mp3recorder.MP3Recorder.DEFAULT_SAMPLING_RATE;

/**
 * Created by hebing on 2016/11/16.
 * http://stackoverflow.com/questions/28506613/using-lame-function-hip-decode-in-android-ndk-to-decode-mp3-return-0
 */

public class MP3Track implements Runnable {

    AudioTrack audioTrack;
    int outBufferSize;
    public byte[] mp3Buf;
    public short[] pcmBuf;
    boolean start = false;
    LinkedList<byte[]> mBuffer;
    Object wait = new Object();
    boolean waiting = false;

    public MP3Track() {
        initParam();
    }

    void initParam() {
        outBufferSize = AudioTrack.getMinBufferSize(DEFAULT_SAMPLING_RATE,
                AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT);

        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, DEFAULT_SAMPLING_RATE,
                AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                outBufferSize,
                AudioTrack.MODE_STREAM);

        //MAXIMO
        mp3Buf = new byte[418];//210 or 418
        pcmBuf = new short[outBufferSize];//8192
        mBuffer = new LinkedList<>();
        Log.d("hebing", "audioTrack.outBytes " + outBufferSize);
    }

    public void start() {
        if (start) {
            Log.d("had be running.");
            return;
        }
        start = true;
        new Thread(this).start();
    }

    public void stop() {
        if (start) {
            start = false;
            synchronized (wait) {
                wait.notify();
            }
        }
    }

    @Override
    public void run() {
        if (audioTrack == null) {
            initParam();
        }
        audioTrack.play();
        while (!Thread.interrupted() && start) {
            byte[] data = getData();
            if (data == null) {
                synchronized (wait) {
                    try {
                        waiting = true;
                        wait.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                continue;
            }
            int ret = audioTrack.write(data, 0, data.length);
            audioTrack.flush();
            Log.d("hebing", "audioTrack.write " + data.length);
        }
        audioTrack.stop();
        audioTrack = null;
    }

    public void putData(byte[] bytes) {
        mBuffer.add(bytes);
        if (waiting) {
            waiting = false;
            synchronized (wait) {
                wait.notify();
            }
        }
    }

    byte[] getData() {
        if (mBuffer.size() > 0) {
            return mBuffer.removeFirst();
        } else {
            return null;
        }
    }

}
